package org.ash.socket.nio;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 单线程 非阻塞版本
 * 缺点
 * 1. 如果有10w连接 ，每次遍历都要遍历10w，是否能够做到每次只遍历有数据的连接
 * @Author: Ashin
 * @Date: 2021/1/25
 * @Description: org.ashin.socket.nio
 * @Version: 1.0.0
 */
public class NioServer {


    public static void main(String[] args) throws Exception {
        ServerSocketChannel serverSocket = ServerSocketChannel.open();
        serverSocket.bind(new InetSocketAddress(8989));

        serverSocket.configureBlocking(false);

        List<SocketChannel> socketChannelList = new ArrayList<>();
        while (true) {
            // 这里不会阻塞
            SocketChannel socketChannel = serverSocket.accept();

            if (socketChannel != null) {
                System.out.println("连接成功..." + socketChannel);

                //设置socket非阻塞，即read（）不在阻塞
                socketChannel.configureBlocking(false);

                socketChannelList.add(socketChannel);
            }


            //遍历连接进行数据的读取
            Iterator<SocketChannel> socketChannelIterator = socketChannelList.iterator();
            while (socketChannelIterator.hasNext()) {
                SocketChannel socket = socketChannelIterator.next();
                ByteBuffer allocate = ByteBuffer.allocate(1024);
                int len = socket.read(allocate);
                if (len > 0) {
                    System.out.println("接收到的消息" + new String(allocate.array()));

                } else if (len == -1) {
                    socketChannelIterator.remove();
                    System.out.println("客户端断开连接");
                }
            }

        }
    }

    private static void handlerRead(SelectionKey selectionKey) {
        try {
            SocketChannel channel = (SocketChannel) selectionKey.channel();


            ByteBuffer buffer = ByteBuffer.allocate(1024);
            int read = -1;
            while ((read = channel.read(buffer)) > 0) {
                buffer.flip();
                String requestText = new String(buffer.array(), 0, read);

                System.out.println(LocalDateTime.now() + ":" + requestText);


                buffer.rewind();

                channel.write(buffer);
            }
            System.out.println("had read ");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}
